<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>JSDoc: Source: packages/search/src/search.vue</title>

    <script src="scripts/prettify/prettify.js"> </script>
    <script src="scripts/prettify/lang-css.js"> </script>
    <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>

<body>

<div id="main">

    <h1 class="page-title">Source: packages/search/src/search.vue</h1>

    



    
    <section>
        <article>
            <pre class="prettyprint source linenums"><code>
&lt;template>
  &lt;div :class="`xdh-go-search ${customClass}`" :style="customStyle" @keyup.enter="search">
    &lt;slot
      :search="search"
      :keyword="keyword"
      :searchResult="searchResult"
      :resultCache="resultCache"
      :index="index"
      :popoverShow="popoverShow"
    >
      &lt;el-popover v-model="popoverShow" ref="popover" trigger="manual" placement="bottom">
        &lt;slot name="popover" :searchResult="searchResult" :keyword="keyword">
          &lt;div>比中类型: {{searchResult.type}}&lt;/div>
          &lt;div>关键字: {{keyword}}&lt;/div>
          &lt;div>比中字段: {{searchResult.keyword}}&lt;/div>
          &lt;div>比中内容: {{searchResult.hit}}&lt;/div>
        &lt;/slot>
      &lt;/el-popover>
      &lt;el-input
        v-popover:popover
        placeholder="输入检索内容"
        v-model="keyword"
        @change="keywordChange"
        size="small"
        class="xdh-go-search__input"
        clearable
      >
        &lt;el-button slot="append" icon="el-icon-search" @click="search">&lt;/el-button>
      &lt;/el-input>
    &lt;/slot>
  &lt;/div>
&lt;/template>
&lt;script>
/**
 * XdhGoSearch组件
 * @module xdh-go-search
 * @description 搜索组件
 */
/**
 * 插槽
 * @member slots
 * @property {String} [default] 搜索框插槽,slot-scope =
 * @property {Function} [default.search] 搜索方法
 * @property {String} [default.keyword] 搜索关键字，用于input数据绑定
 * @property {Array} [default.resultCache] 当前搜索结果列表
 * @property {Function} [default.index] 当前搜索结果下标
 * @property {Object} [default.searchResult] 当前搜索结果
 * @property {String} [default.searchResult.keyword] 比中字段
 * @property {String} [default.searchResult.hit] 比中内容
 * @property {String} [default.searchResult.type] 比中类型
 * @property {Boolean} [default.popoverShow] popover显示
 */
/**
 * 插槽
 * @member slots
 * @property {String} [popover] 提示框内容插槽, 当设置了default插槽时，该插槽无效，slot-scope =
 * @property {Object} [popover.keyword] 关键字
 * @property {Object} [popover.searchResult] 当前搜索结果
 * @property {String} [popover.searchResult.keyword] 比中字段
 * @property {String} [popover.searchResult.hit] 比中内容
 * @property {String} [popover.searchResult.type] 比中类型
 */
export default {
  name: 'XdhGoSearch',
  components: {},
  /**
   * 参数属性
   * @property {Object} [diagram=null] go.Diagram对象
   * @property {Boolean} [pullCenter=true] 搜索后是否将结果居中显示
   * @property {Boolean} [ignoreCase=true] 是否忽略大小写
   * @property {Array} [nodeKeys=['key']] 搜索节点数据字段，可深度搜索，如: ['info.name', 'remark.desc']
   * @property {Array} [linkKeys=['key']] 搜索连线数据字段，可深度搜索，如: ['info.name', 'remark.desc']
   * @property {Object} [mode=node] 搜索节点或连线, 'node'/'link'/'node,link'/'link,node'
   * @property {String} [customClass=''] 容器自定义类
   * @property {Object} [customStyle={}] 容器自定义类
   * @property {Number} [popDuration={}] 提示框停留的毫秒数，设置为0时不显示提示框
   */
  props: {
    diagram: {
      type: Object,
      default() {
        return null
      }
    },
    pullCenter: {
      type: Boolean,
      default: true
    },
    ignoreCase: {
      type: Boolean,
      default: true
    },
    // 搜索节点的key
    nodeKeys: {
      type: Array,
      default() {
        return ['key']
      }
    },
    // 搜索连接的key
    linkKeys: {
      type: Array,
      default() {
        return ['key']
      }
    },
    // 搜索模式， 可以只搜索节点或者连接，或者两者都搜索
    mode: {
      type: String,
      default() {
        return 'node'
      },
      validator(val) {
        return ['node', 'link', 'node,link', 'link,node'].includes(val)
      }
    },
    customClass: {
      type: String,
      default: ''
    },
    customStyle: {
      type: Object,
      default() {
        return {}
      }
    },
    popDuration: {
      type: Number,
      default: 5000
    }
  },
  data() {
    return {
      keyword: '',
      // 用于放置搜索关键词，如果关键词不变，顺次查找下一个节点
      keywordCache: '',
      // 用来放置搜索的结果数组，与index结合实现查找下一个功能
      resultCache: [],
      index: 0,
      searchResult: {},
      popoverShow: false,
      popTimeout: null
    }
  },
  computed: {},
  methods: {
    keywordChange() {
      this.searchResult = {}
    },
    search() {
      if (!this.keyword) {
        /**
         * 搜索错误时触发
         * @event on-error
         * @param {String} error 错误信息
         */
        this.$emit('on-error', 'keyword-empty')
        return
      }
      clearTimeout(this.popTimeout)
      // 如果搜索关键字不变，index加1
      if (this.keyword === this.keywordCache) {
        this.index = (this.index + 1) % this.resultCache.length
      } else {
        this.index = 0
      }
      this.searchNode()
      if (this.resultCache.length !== 0) {
        this.searchResult = this.resultCache[this.index]
        if (this.popDuration &amp;&amp; this.searchResult.hit) {
          this.popoverShow = true
        }
        this.popTimeout = setTimeout(() => {
          this.popoverShow = false
        }, this.popDuration)
        let node = this.searchResult.node
        node.isSelected = true
        if (this.pullCenter) {
          let rect = node.actualBounds
          this.diagram.centerRect(rect)
        }
        /**
         * 搜索成功时触发
         * @event on-search
         * @param {Object} node 搜索到的节点
         * @param {Array} resultCache 搜索到的结果数组
         * @param {Number} index 搜索到的结果下标
         * @param {String} keyword 搜索关键字
         */
        this.$emit(
          'on-search',
          node,
          this.resultCache,
          this.index,
          this.keyword
        )
      } else {
        this.$emit('on-error', 'no-result')
      }
    },
    searchNode() {
      this.keywordCache = this.keyword
      this.diagram.clearSelection()
      let nodes = []
      // 查找节点数组
      if (this.mode.includes('node')) {
        this.diagram.nodes.each(n => {
          let hit = false // 是否命中
          let hitKeywords = []
          let hitText = []
          this.nodeKeys.forEach(k => {
            let keywords = k.split('.')
            let d = this.getData(n.data, keywords)
            if (typeof d === 'string') {
              if (this.ignoreCase) {
                if (d.toLowerCase().includes(this.keyword.toLowerCase())) {
                  hit = true
                  hitKeywords.push(k)
                  hitText.push(`${d}`)
                }
              } else {
                if (d.includes(this.keyword)) {
                  hit = true
                  hitKeywords.push(k)
                  hitText.push(`${d}`)
                }
              }
            }
          })
          if (hit) {
            nodes.push({
              type: 'node',
              keyword: hitKeywords.join(','),
              hit: hitText.join('\n'),
              node: n
            })
          }
        })
      }
      if (this.mode.includes('link')) {
        this.diagram.links.each(n => {
          let hit = false
          let hitKeywords = []
          let hitText = []
          this.linkKeys.forEach(k => {
            let keywords = k.split('.')
            let d = this.getData(n.data, keywords)
            if (typeof d === 'string') {
              if (this.ignoreCase) {
                if (d.toLowerCase().includes(this.keyword.toLowerCase())) {
                  hit = true
                  hitKeywords.push(k)
                  hitText.push(`${d}`)
                }
              } else {
                if (d.includes(this.keyword)) {
                  hit = true
                  hitKeywords.push(k)
                  hitText.push(`${d}`)
                }
              }
            }
            if (hit) {
              nodes.push({
                type: 'link',
                keyword: hitKeywords.join(','),
                hit: hitText.join('\n'),
                node: n
              })
            }
          })
        })
      }
      //   console.log(nodes.map(r => r.data.key))
      if (nodes.length !== 0) {
        this.resultCache = nodes
      } else {
        this.resultCache = []
      }
    },
    getData(data, keywords) {
      if (keywords.length !== 0) {
        let key = keywords.shift()
        if (data[key]) {
          return this.getData(data[key], keywords)
        } else {
          return ''
        }
      } else {
        return data
      }
    }
  },
  created() {}
}
&lt;/script>
&lt;style type="text/scss" lang="scss" scoped>
&lt;/style>
</code></pre>
        </article>
    </section>




</div>

<nav>
    <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-utils_directives_draggable.html">utils/directives/draggable</a></li><li><a href="module-utils_directives_resizable.html">utils/directives/resizable</a></li><li><a href="module-utils_events.html">utils/events</a></li><li><a href="module-utils_storage.html">utils/storage</a></li><li><a href="module-xdh-go.html">xdh-go</a></li><li><a href="module-xdh-go-circle-menu.html">xdh-go-circle-menu</a></li><li><a href="module-xdh-go-draft.html">xdh-go-draft</a></li><li><a href="module-xdh-go-html.html">xdh-go-html</a></li><li><a href="module-xdh-go-layout.html">xdh-go-layout</a></li><li><a href="module-xdh-go-overview.html">xdh-go-overview</a></li><li><a href="module-xdh-go-search.html">xdh-go-search</a></li><li><a href="module-xdh-go-select.html">xdh-go-select</a></li><li><a href="module-xdh-go-snapshot.html">xdh-go-snapshot</a></li><li><a href="module-xdh-go-tool.html">xdh-go-tool</a></li><li><a href="module-xdh-go-tooltiip.html">xdh-go-tooltiip</a></li><li><a href="module-xdh-go-view.html">xdh-go-view</a></li><li><a href="module-xdh-go-viewer.html">xdh-go-viewer</a></li></ul><h3>Classes</h3><ul><li><a href="module-utils_directives_draggable-Draggable.html">Draggable</a></li><li><a href="module-utils_directives_resizable-Resizable.html">Resizable</a></li><li><a href="module-utils_events-Events.html">Events</a></li></ul><h3>Events</h3><ul><li><a href="module-xdh-go-view.html#~event:item-click">item-click</a></li><li><a href="module-xdh-go-select.html#~event:on-change">on-change</a></li><li><a href="module-xdh-go-search.html#~event:on-error">on-error</a></li><li><a href="module-xdh-go-circle-menu.html#~event:on-item-click">on-item-click</a></li><li><a href="module-xdh-go.html#~event:on-load-data">on-load-data</a></li><li><a href="module-xdh-go.html#~event:on-ready">on-ready</a></li><li><a href="module-xdh-go-search.html#~event:on-search">on-search</a></li><li><a href="module-xdh-go-snapshot.html#~event:on-snap">on-snap</a></li></ul><h3>Global</h3><ul><li><a href="global.html#animationPool">animationPool</a></li><li><a href="global.html#bindToState">bindToState</a></li><li><a href="global.html#ease">ease</a></li><li><a href="global.html#easeInBack">easeInBack</a></li><li><a href="global.html#easeInBounce">easeInBounce</a></li><li><a href="global.html#easeInCirc">easeInCirc</a></li><li><a href="global.html#easeInCubic">easeInCubic</a></li><li><a href="global.html#easeInElastic">easeInElastic</a></li><li><a href="global.html#easeInExpo">easeInExpo</a></li><li><a href="global.html#easeInOutBack">easeInOutBack</a></li><li><a href="global.html#easeInOutBounce">easeInOutBounce</a></li><li><a href="global.html#easeInOutCubic">easeInOutCubic</a></li><li><a href="global.html#easeInOutQuad">easeInOutQuad</a></li><li><a href="global.html#easeInOutQuart">easeInOutQuart</a></li><li><a href="global.html#easeInOutQuint">easeInOutQuint</a></li><li><a href="global.html#easeInOutSine">easeInOutSine</a></li><li><a href="global.html#easeInQuad">easeInQuad</a></li><li><a href="global.html#easeInQuart">easeInQuart</a></li><li><a href="global.html#easeInQuint">easeInQuint</a></li><li><a href="global.html#easeInSine">easeInSine</a></li><li><a href="global.html#easeOutBack">easeOutBack</a></li><li><a href="global.html#easeOutBounce">easeOutBounce</a></li><li><a href="global.html#easeOutCirc">easeOutCirc</a></li><li><a href="global.html#easeOutCubic">easeOutCubic</a></li><li><a href="global.html#easeOutElastic">easeOutElastic</a></li><li><a href="global.html#easeOutExpo">easeOutExpo</a></li><li><a href="global.html#easeOutQuad">easeOutQuad</a></li><li><a href="global.html#easeOutQuart">easeOutQuart</a></li><li><a href="global.html#easeOutQuint">easeOutQuint</a></li><li><a href="global.html#easeOutSine">easeOutSine</a></li><li><a href="global.html#extendOption">extendOption</a></li><li><a href="global.html#genOption">genOption</a></li><li><a href="global.html#getHandler">getHandler</a></li><li><a href="global.html#handleEvents">handleEvents</a></li><li><a href="global.html#handleParts">handleParts</a></li><li><a href="global.html#horPanel%25E6%25B0%25B4%25E5%25B9%25B3%25E5%25B8%2583%25E5%25B1%2580">horPanel 水平布局</a></li><li><a href="global.html#makePort">makePort</a></li><li><a href="global.html#node%25E8%258A%2582%25E7%2582%25B9%25E5%25AE%259A%25E4%25B9%2589">node 节点定义</a></li><li><a href="global.html#removeGray">removeGray</a></li><li><a href="global.html#setGray">setGray</a></li><li><a href="global.html#shapeParamsBinding">shapeParamsBinding</a></li><li><a href="global.html#spotPanelspot%25E5%25B8%2583%25E5%25B1%2580">spotPanel spot布局</a></li><li><a href="global.html#verPanel%25E5%259E%2582%25E7%259B%25B4%25E5%25B8%2583%25E5%25B1%2580">verPanel 垂直布局</a></li></ul>
</nav>

<br class="clear">

<footer>
    Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 3.6.3</a> on Tue Nov 05 2019 16:15:35 GMT+0800 (GMT+08:00)
</footer>

<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
